//
// Created by Administrator on 2019/11/2.
//

#include <dirent.h>
#include <jni.h>
#include <sys/stat.h>
#include <unistd.h>
#include "file_utils.h"
#include "log_utils.h"
#include "shell_utils.h"
#include "string_utils.h"

bool dir_exist(const std::string &path) {
    DIR* dir=opendir(path.c_str());
    bool exist=dir!= nullptr;
    if(dir)
        closedir(dir);
    return exist;
}

bool dir_writable(const std::string &path_str){
    const char* path=path_str.c_str();
    DIR* dir=opendir(path);
    if(!dir)//限定这是一个目录
        return false;
    closedir(dir);
    return generic_writable(path_str);
}

bool dir_readable(const std::string &path_str){
    const char* path=path_str.c_str();
    DIR* dir=opendir(path);
    if(!dir)//限定这是一个目录
        return false;
    closedir(dir);
    return generic_readable(path_str);
}


#define MODE_0777 (S_IRWXU | S_IRWXG | S_IRWXO)

#define MODE_0744 (S_IRWXU | S_IRGRP | S_IROTH)

bool get_or_create_dir(const std::string &path,bool readable_accepted) {
    if(readable_accepted
    &&dir_readable(path))
        return true;
    if(dir_writable(path))
        return true;
    return mkdir(path.c_str(),MODE_0744)==JNI_OK;
}

bool access_int_to_bool(const std::string &path,int mode){
    return access(path.c_str(),mode)==JNI_OK;
}

bool generic_writable(const std::string &path_str) {
    return access_int_to_bool(path_str,W_OK);
}

bool generic_readable(const std::string &path_str) {
    return access_int_to_bool(path_str,R_OK);
}

int read_text_file(const std::string &path,std::string &result){
   std::string cmd=std::string("cat").append(" ").append(path);
    AKLog("cmd:%s\n",cmd.c_str());
    return shell_with_return(cmd,result)==JNI_OK;
}

bool generic_exist(const std::string &path) {
    return access_int_to_bool(path,(F_OK | R_OK));
}

void append_path(const std::string &old_path,const std::string &child,
        std::string &result){
    result.append(old_path);
    result.append("/");
    result.append(child);
}

static bool DEBUGABLE=true;

void enum_files(const std::string &path,bool contain_sub_dirs,
        std::vector<std::string> &result_list) {
    const char *p_path = path.c_str();
    DIR *dp = opendir(p_path);
    if (!dp) {
        AKLogErr("fail to open dir:%s\n", p_path);
        return;
    }
    //chdir (dir);                     // 切换到当前目录
    while (true)  // 获取下一级目录信息，如果未否则循环
    {
        struct dirent *entry = readdir(dp);
        if (!entry)
            break;
        struct stat stat_buf;
        lstat(entry->d_name, &stat_buf); // 获取下一级成员属性
        std::string child_path;
        append_path(path, entry->d_name, child_path); //获取当前entry的全路径
        if (dir_exist(child_path))//跳过目录
            continue;
        std::string file_path;
        append_path(path, entry->d_name, file_path);
        if (DEBUGABLE)
            AKLog("%s\n", file_path.c_str());
        result_list.push_back(file_path);
    }
    closedir(dp);
}
